package com.demiroot.server;

import java.net.URLDecoder;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Map.Entry;
import java.util.regex.Pattern;

public class HeaderData {
	private Map<HeaderField, String> feilds = new HashMap<HeaderField, String>();
	private RequestMethod method;
	private String version;
	private String uri;
	private String query;
	
	public enum HeaderField {
		ACCEPT, ACCEPT_CHARSET, ACCEPT_ENCODING, ACCEPT_LANGUAGE, ACCEPT_RANGES,
		AGE, ALLOW, AUTHORIZATION, CACHE_CONTROL, CONNECTION, CONTENT_ENCODING, 
		CONTENT_LANGUAGE, CONTENT_LENGTH, CONTENT_LOCATION, CONTENT_MD5, 
		CONTENT_RANGE, CONTENT_TYPE, COOKIE, DATE, EXPECT, EXPIRES, FROM, HOST, IF_MATCH,
		IF_MODIFIED_SINCE, IF_NONE_MATCH, IF_RANGE, IF_UNMODIFIED_SINCE, 
		LAST_MODIFIED, LOCATION, MAX_FORWARDS, PRAGMA, PROXY_AUTHENTICATE, 
		PROXY_AUTHORIZATION, RANGE, REFERER, RETRY_AFTER, SERVER, TE, TRAILER, 
		TRANSFER_ENCODING, UPGRADE, USER_AGENT, VARY, VIA, WARNING,
		WWW_AUTHENTICATE; 
	}
	
	public enum RequestMethod {
		OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT;
	}
	
	public static final String[] headers = new String[]{"Accept","Accept-Charset", 
		"Accept-Encoding", "Accept-Language", "Accept-Ranges", "Age", "Allow", 
		"Authorization", "Cache-Control", "Connection", "Content-Encoding", 
		"Content-Language", "Content-Length", "Content-Location", "Content-MD5",
		"Content-Range", "Content-Type", "Cookie", "Date", "Expect", "Expires", "From", "Host",
		"If-Match", "If-Modified-Since", "If-None-Match", "If-Range", "If-Unmodified-Since",
		"Last-Modified", "Location", "Max-Forwards", "Pragma", "Proxy-Authenticate",
		"Proxy-Authorization", "Range", "Referer", "Retry-After", "Server", "TE", "Trailer",
		"Transfer-Encoding", "Upgrade", "User-Agent", "Vary", "Via", "Warning", 
		"WWW-Authenticate"};
	
	public HeaderData(String all) {
		Scanner s = new Scanner(all);
		method = RequestMethod.valueOf(s.next().trim().toUpperCase());
		uri = s.next().trim();
		
		if (uri.charAt(0) == '/') {
			uri = uri.replaceFirst("/", "");
		}
		
		if (!uri.equals("")) {
			Scanner s2 = new Scanner(uri);
			s2.useDelimiter("[?]");
			uri = s2.next();
			if (s2.hasNext()) {
				query = s2.nextLine();
				query = query.substring(1, query.length());
			} else {
				query = "";
			}
		} else {
			query = "";
		}
		try {
		query = URLDecoder.decode(query, "utf-8");
		} catch (Exception e){}
		
		version =  s.next().trim().toUpperCase().replaceAll("HTTP/", "");
		
		while (s.hasNext()) {
			String catagory = s.next().trim().replaceAll(":","");			
			for (int x = 0; x < headers.length; x++ ) {
				if (headers[x].equalsIgnoreCase(catagory)) {
					String line = s.nextLine().trim();
					while (line.endsWith("\\")) {
						line = line.substring(0, line.length()-2) + " " + 
							s.nextLine().trim();
					}
					feilds.put(HeaderField.values()[x], line);
				}
			}
		}
		s.close();
	}
	
	public HeaderData() {
		//sets the defaults
		set(HeaderField.CONNECTION, "close");
		set(HeaderField.DATE, ServerUtils.getWebDate(Calendar.getInstance()));
	}
	
	public void set(HeaderField h, String value) {
		feilds.put(h, value);
	}
	
	public String get(HeaderField hl) {
		return feilds.get(hl);
	}
	
	public int getInt(HeaderField hl) {
		String sNum = get(hl); 
		if (sNum != null) {
			return Integer.parseInt(sNum);
		}
		return 0;
	}
	
	public RequestMethod getRequestMethod() {
		return method;
	}
	
	public String getVersion() {
		return version;
	}
	
	public String getURI() {
		return uri;
	}
	
	public void printAllValues() {
		for (HeaderField hf : feilds.keySet()) {
			Logger.log("header fields", hf + ": " + feilds.get(hf));
		}
	}
	
	public String getQuery() {
		return query;
	}
	
	public void setQuery(String query) {
		this.query = query;
	}
	
	public String getCookieValue(String key) {
		String ret = null;
		String allCookies = get(HeaderField.COOKIE);
		if (allCookies == null) return null;
		
		Scanner scan = new Scanner(allCookies);
		
		scan.useDelimiter(Pattern.compile(":|;"));
		while (scan.hasNext()) {
			String s = scan.next().trim();
			if (s.startsWith(key)) {
				ret = s.substring(s.indexOf("=")+1, s.length());
			}
		}
		return ret;
	}
	
	public String toString() {
		String s = "";
		for (Entry<HeaderField, String> entry : feilds.entrySet()) {
			s+= entry.getKey().toString() + " : " + entry.getValue() + Server.ENDL;
		}
		return s;
	}
	
	public void setURI(String uri) {
		this.uri = uri;
	}
	
	public Map<HeaderData.HeaderField, String> getMap() {
		return feilds;
	}
}
